<!doctype html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>JS Application DbC Example</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
    <script src="./js/jquery.jsa.js" type="text/javascript"></script>
    <script src="./js/jquery.jsa-dbc.js" type="text/javascript"></script>
</head>
<body>

<script  type="text/javascript">
(function( $ ) {
    var ContractSample1 = {
        methodA : ["number", "object"]
    }
    var ContractSample2 = {
        methodA : {
            onEntry:  ["string", $.jsa.BaseAbstract],
            validators: [
                function(arg){ return arg.length < 20; },
                function(arg){ return true },
            ],
            onExit: "boolean"
        },
        methodB : {
            onEntry:  [],
            onExit: "number"
        }
    }
    var ModuleSample1 = function() {
        return $.jsa.extend({
            name: 'ModuleSample1',
            contracts: ContractSample1
       }, $.jsa.BaseAbstract);
    };
    var ModuleSample2 = function() {
        return $.jsa.extend({
            name: 'ModuleSample2',
            contracts: ContractSample1,
            methodA: function(arg1, arg2) {
                print(this.name + ":methodA is running");
            }
       }, $.jsa.BaseAbstract);
    };
    var ModuleSample3 = function() {
        return $.jsa.extend({
            name: 'ModuleSample3',
            contracts: ContractSample2,
            methodA: function(arg1, arg2) {
                print(this.name + ":methodA is running");
                return true;
            },
            methodB: function() {
                print(this.name + ":methodB is running");
                return true;
            }
       }, $.jsa.BaseAbstract);
    };

    /**
    * Usage 
    */
    var print = function(text) { document.writeln(text + '<br />'); };
    print('Sample 1. Module violates the contract');
    try {
        var m1 = ModuleSample1().getInstance();
    } catch(e) {
        print(e);
    }
    
    var m2 = ModuleSample2().getInstance(),
        m3 = ModuleSample3().getInstance();

    print('Sample 2. Module fails on contract preconditions');
    try {
        m2.methodA("a string where a number excpected", {});
    } catch(e) {
        print(e);
    }
    print('Sample 2. Module passes contract preconditions');
    m2.methodA(42, {});
    m3.methodA("short string", m2); // m2 is an instance of BaseAbstract
    print('Sample 3. Module fails on contract validator');
    try {
        m3.methodA("string, which is more than 20 chars", m2);
    } catch(e) {
        print(e);
    }
    print('Sample 4. Module fails on contract postcondition');
    try {
        m3.methodB();
    } catch(e) {
        print(e);
    }

// Output:
// Sample 1. Module violates the contract
// SyntaxError: One of the contracts, the object agreed on, contains abstract method 'methodA'
// and it must be implemented by the object
// Sample 2. Module fails on contract preconditions
// TypeError: ModuleSample2.methodA: argument #1 is required to be a number
// Sample 2. Module passes contract preconditions
// ModuleSample2:methodA is running
// ModuleSample3:methodA is running
// Sample 3. Module fails on contract validator
// RangeError: ModuleSample3.methodA: argument #1 is outside of its valid range
// Sample 4. Module fails on contract postcondition
// ModuleSample3:methodB is running
// TypeError: ModuleSample3.methodB: return value is required to be a number

})( jQuery );
</script>

    </body>
</html>